home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlb20 / lib / _addsubd.cpp next >
Text File  |  1992-03-30  |  5KB  |  202 lines

  1. #ifndef __M68881__
  2. #ifndef    sfp004
  3. | double floating point add/subtract routine
  4. |
  5. | written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  6. | Based on a 80x86 floating point packet from comp.os.minix, written by P.Housel
  7. |
  8. |
  9. | Revision 1.3, kub 01-90 :
  10. | added support for denormalized numbers
  11. |
  12. | Revision 1.2, kub 01-90 :
  13. | replace far shifts by swaps to gain speed
  14. |
  15. | Revision 1.1, kub 12-89 :
  16. | Ported over to 68k assembler
  17. |
  18. | Revision 1.0:
  19. | original 8088 code from P.S.Housel
  20.  
  21.     .text
  22.     .even
  23.     .globl    __subdf3, ___subdf3
  24.     .globl    __adddf3, ___adddf3
  25.  
  26. __subdf3:
  27. ___subdf3:
  28.     eorb    #0x80,sp@(12)    | reverse sign of v
  29. __adddf3:
  30. ___adddf3:
  31.     lea    sp@(4),a0    | pointer to u and v parameter
  32.     moveml    d2-d7,sp@-    | save registers
  33.     moveml    a0@,d4-d5/d6-d7    | d4-d5 = v, d6-d7 = u
  34.  
  35.     movel    d6,d0        | d0 = u.exp
  36.     swap    d0
  37.     movel    d6,d2        | d2.h = u.sign
  38.     movew    d0,d2
  39.     lsrw    #4,d0
  40.     andw    #0x07ff,d0    | kill sign bit
  41.  
  42.     movel    d4,d1        | d1 = v.exp
  43.     swap    d1
  44.     eorw    d1,d2        | d2.l = u.sign ^ v.sign
  45.     lsrw    #4,d1
  46.     andw    #0x07ff,d1    | kill sign bit
  47.  
  48.     andl    #0x0fffff,d6    | remove exponent from u.mantissa
  49.     tstw    d0        | check for zero exponent - no leading "1"
  50.     beq    0f
  51.     orl    #0x100000,d6    | restore implied leading "1"
  52.     bra    1f
  53. 0:    addw    #1,d0        | "normalize" exponent
  54. 1:
  55.     andl    #0x0fffff,d4    | remove exponent from v.mantissa
  56.     tstw    d1        | check for zero exponent - no leading "1"
  57.     beq    0f
  58.     orl    #0x100000,d4    | restore implied leading "1"
  59.     bra    1f
  60. 0:    addw    #1,d1        | "normalize" exponent
  61. 1:
  62.     clrw    d3        | (put initial zero rounding bits in d3)
  63.     negw    d1        | d1 = u.exp - v.exp
  64.     addw    d0,d1
  65.     beq    5f        | exponents are equal - no shifting neccessary
  66.     bgt    1f        | not equal but no exchange neccessary
  67.     exg    d4,d6        | exchange u and v
  68.     exg    d5,d7
  69.     subw    d1,d0        | d0 = u.exp - (u.exp - v.exp) = v.exp
  70.     negw    d1
  71.     tstw    d2        | d2.h = u.sign ^ (u.sign ^ v.sign) = v.sign
  72.     bpl    1f
  73.     bchg    #31,d2
  74. 1:
  75.     cmpw    #53,d1        | is u so much bigger that v is not
  76.     bge    7f        | significant ?
  77.  
  78.     movew    #10-1,d3    | shift u left up to 10 bits to minimize loss
  79. 2:
  80.     addl    d7,d7
  81.     addxl    d6,d6
  82.     subw    #1,d0        | decrement exponent
  83.     subw    #1,d1        | done shifting altogether ?
  84.     dbeq    d3,2b        | loop if still can shift u.mant more
  85.     clrw    d3
  86. 3:
  87.     cmpw    #16,d1        | see if fast rotate possible
  88.     blt    4f
  89.     orb    d5,d3        | set rounding bits
  90.     orb    d2,d3
  91.     sne    d2        | "sticky byte"
  92.     movew    d5,d3
  93.     lsrw    #8,d3
  94.     movew    d4,d5        | rotate by swapping register halfs
  95.     swap    d5
  96.     clrw    d4
  97.     swap    d4
  98.     subw    #16,d1
  99.     bra    3b
  100. 0:
  101.     lsrl    #1,d4        | shift v.mant right the rest of the way
  102.     roxrl    #1,d5        | to line it up with u.mant
  103.     orb    d3,d2        | set "sticky byte" if necessary
  104.     roxrw    #1,d3        | shift into rounding bits
  105. 4:    dbra    d1,0b        | loop
  106.     andb    #1,d2        | see if "sticky bit" should be set
  107.     orb    d2,d3
  108. 5:
  109.     tstw    d2        | are the signs equal ?
  110.     bpl    6f        | yes, no negate necessary
  111.  
  112.     negb    d3        | negate rounding bits and v.mant
  113.     negl    d5
  114.     negxl    d4
  115. 6:
  116.     addl    d5,d7        | u.mant = u.mant + v.mant
  117.     addxl    d4,d6
  118.     bcs    7f        | need not negate
  119.     tstw    d2        | opposite signs ?
  120.     bpl    7f        | do not need to negate result
  121.  
  122.     negb    d3        | negate rounding bits and u.mant
  123.     negl    d7
  124.     negxl    d6
  125.     notl    d2        | switch sign
  126. 7:
  127.     movel    d6,d4        | move result for normalization
  128.     movel    d7,d5
  129.     moveb    d3,d1        | put rounding bits in d1 for norm_df
  130.     swap    d2        | put sign into d2 (exponent is in d0)
  131.     jmp    norm_df        | leave registers on stack for norm_df
  132. #else    sfp004
  133. | double precision floating point stuff for Atari-gcc using the SFP004
  134. | developed with gas
  135. |
  136. | double floating point add/subtract routine
  137. |
  138. | M. Ritzert (mjr at dmzrzu71)
  139. |
  140. | 4.10.1990
  141. |
  142. | no NAN checking implemented since the 68881 treats this situation "correct",
  143. | i.e. according to IEEE
  144.  
  145. | addresses of the 68881 data port. This choice is fastest when much data is
  146. | transferred between the two processors.
  147.  
  148. comm =     -6
  149. resp =    -16
  150. zahl =      0
  151.  
  152. | waiting loop ...
  153. |
  154. | wait:
  155. | ww:    cmpiw    #0x8900,a0@(resp)
  156. |     beq    ww
  157. | is coded directly by
  158. |    .long    0x0c688900, 0xfff067f8
  159.  
  160.     .text
  161.     .even
  162.     .globl    __subdf3, ___subdf3
  163.     .globl    __adddf3, ___adddf3
  164.  
  165. __subdf3:
  166. ___subdf3:
  167. | double precision subtraction
  168. | sub second arg from fp0
  169.     lea    0xfffa50,a0
  170.     movew    #0x5400,a0@(comm)    | load first argument to fp0
  171.     cmpiw    #0x8900,a0@(resp)    | check
  172.     movel    a7@(4),a0@
  173.     movel    a7@(8),a0@
  174.     movew    #0x5428,a0@(comm)
  175.     .long    0x0c688900, 0xfff067f8
  176.     movel    a7@(12),a0@
  177.     movel    a7@(16),a0@
  178.     movew    #0x7400,a0@(comm)    | result to d0/d1
  179.     .long    0x0c688900, 0xfff067f8
  180.     movel    a0@,d0
  181.     movel    a0@,d1
  182.      rts
  183.  
  184. __adddf3:
  185. ___adddf3:
  186.     lea    0xfffa50,a0
  187.     movew    #0x5400,a0@(comm)        | load fp0
  188.     cmpiw    #0x8900,a0@(resp)        | got it?
  189.     movel    a7@(4),a0@            | take a hi from stack to FPU
  190.     movel    a7@(8),a0@            | take a lo from stack to FPU
  191.     movew    #0x5422,a0@(comm)        | add second arg to fp0
  192.     .long    0x0c688900, 0xfff067f8
  193.     movel    a7@(12),a0@            | move b hi from stack to FPU
  194.     movel    a7@(16),a0@            | move b lo from stack to FPU
  195.     movew    #0x7400,a0@(comm)        | result to d0/d1
  196.     .long    0x0c688900, 0xfff067f8
  197.     movel    a0@,d0                | download result
  198.     movel    a0@,d1                | download result
  199.      rts
  200. #endif    sfp004
  201. #endif    __M68881__
  202.